﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MacomberMapSystem.Common.Database;
using System.ComponentModel;
using MacomberMapSystem.Common.Serialization;
using System.Xml;
using System.Data.Common;
using MacomberMapSystem.Common.CIM;

namespace MacomberMapSystem.Common.Processing
{
    /// <summary>
    /// This class is responsible for modifying attributes for elements that fit certain criteria
    /// </summary>
    public class CIM_AttributeModifier: CIM_Processor
    {
        #region Variable declarations
        /// <summary>Report the name of our process</summary>
        public override string ProcessName
        {
            get { return "Attribute Modifier"; }
        }

        private List<CIM_AttributeToModify> AttributesToModify
        {
            get { return _AttributesToModify; }
            set { _AttributesToModify = value; }
        }         
        private List<CIM_AttributeToModify> _AttributesToModify = new List<CIM_AttributeToModify>();   
        #endregion

        #region Initialization
        /// <summary>
        /// Intialize a new attribute modifier instance
        /// </summary>
        /// <param name="xElem"></param>
        /// <param name="NamedParameters"></param>
        /// <param name="Repository"></param>
        public CIM_AttributeModifier(XmlElement xElem, Dictionary<String,Object> NamedParameters, MM_Repository Repository)
            : base(xElem, NamedParameters, Repository)
        {
            foreach (XmlElement xChild in xElem.SelectNodes("AttributeToModify"))
                _AttributesToModify.Add(new CIM_AttributeToModify(xChild, Repository));
        }

        /// <summary>
        /// Perform our process
        /// </summary>
        /// <param name="DbConn"></param>
        /// <returns></returns>
        public override CIM_Processor.enumProcessState InitiateProcess(MM_Database_Connector DbConn)
        {

            //Go throuhg all attributes to modify. If they pass the test, assign the attribute modifications.
            MM_Database_Model CIM = NamedParameters["Model"] as MM_Database_Model;
            foreach (CIM_AttributeToModify AttrToModify in _AttributesToModify)
                foreach (CIM_Element Elem in CIM.ElementsOfType(AttrToModify.ElementType))
                {
                    String Value = AttrToModify.ParseConditionValue ? Elem[AttrToModify.TestConditionValue] : AttrToModify.TestConditionValue;
                    if (!AttrToModify.TestEqual ^ String.Equals(Elem[AttrToModify.TestConditionAttribute], AttrToModify.TestConditionValue, StringComparison.CurrentCultureIgnoreCase))
                        foreach (String Attr in AttrToModify.Attribute)
                        {
                            String[] splStr = Attr.Split('=');
                            CIM_Element_Difference.ModifyAttribute(Elem, splStr[0], splStr[1]);
                        }
                }
            return enumProcessState.Completed;
        }
        #endregion

        /// <summary>
        /// This class holds information on an attribuite to be modified
        /// </summary>
        public class CIM_AttributeToModify : MM_Serializable
        {
            #region Variable declarations
            /// <summary>The collection of attributes to be set</summary>
            public List<String> Attribute
            {
                get { return _Attribute; }
                set { _Attribute = value; }
            }

            /// <summary>The test condition value</summary>
            public string TestConditionValue
            {
                get { return _TestConditionValue; }
                set { _TestConditionValue = value; }
            }

            /// <summary>The test condition attribute</summary>
            public string TestConditionAttribute
            {
                get { return _TestConditionAttribute; }
                set { _TestConditionAttribute = value; }
            }

            /// <summary>
            /// The element type to be searched
            /// </summary>
            public string ElementType
            {
                get { return _ElementType; }
                set { _ElementType = value; }
            }



            /// <summary>
            /// Whether the equality of two elements indicates the modification should take place
            /// </summary>
            public bool TestEqual
            {
                get { return _TestEqual; }
                set { _TestEqual = value; }
            }

            /// <summary>
            /// Whether the conditional value should be parsed
            /// </summary>
            public bool ParseConditionValue
            {
              get { return _ParseConditionValue; }
              set { _ParseConditionValue = value; }
            }


            private bool _TestEqual = true, _ParseConditionValue;

            private string _ElementType, _TestConditionAttribute, _TestConditionValue;
            private List<String> _Attribute = new List<string>();
            #endregion

            #region Initialization
            /// <summary>
            /// Initailize a new Attribute to modify
            /// </summary>
            /// <param name="Repository"></param>
            /// <param name="xElem"></param>
            public CIM_AttributeToModify(XmlElement xElem, MM_Repository Repository)
                : base(xElem, Repository)
            {
            }

            /// <summary>
            /// Initialize a new attribute to modify
            /// </summary>
            /// <param name="dRd"></param>
            /// <param name="xDoc"></param>
            /// <param name="Repository"></param>
            public CIM_AttributeToModify(DbDataReader dRd, XmlDocument xDoc, MM_Repository Repository)
                : base(dRd, xDoc, Repository)
            {
            }
            #endregion
        }
    }
}
